/**
 * \file Ifx_Ssw_CompilersDcc.h
 * \brief Startup Software for DCC compiler options
 *
 * \version iLLD_1_0_1_11_0
 * \copyright Copyright (c) 2018 Infineon Technologies AG. All rights reserved.
 *
 *                                 IMPORTANT NOTICE
 *
 *
 * Use of this file is subject to the terms of use agreed between (i) you or 
 * the company in which ordinary course of business you are acting and (ii) 
 * Infineon Technologies AG or its licensees. If and as long as no such 
 * terms of use are agreed, use of this file is subject to following:


 * Boost Software License - Version 1.0 - August 17th, 2003

 * Permission is hereby granted, free of charge, to any person or 
 * organization obtaining a copy of the software and accompanying 
 * documentation covered by this license (the "Software") to use, reproduce,
 * display, distribute, execute, and transmit the Software, and to prepare
 * derivative works of the Software, and to permit third-parties to whom the 
 * Software is furnished to do so, all subject to the following:

 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer, must
 * be included in all copies of the Software, in whole or in part, and all
 * derivative works of the Software, unless such copies or derivative works are
 * solely in the form of machine-executable object code generated by a source
 * language processor.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.

 *
 */

#ifndef IFX_SSW_COMPILERSDCC_H_
#define IFX_SSW_COMPILERSDCC_H_

/******************************************************************************/
/*----------------------------------Includes----------------------------------*/
/******************************************************************************/

/******************************************************************************/
/*-----------------------------------Macros-----------------------------------*/
/******************************************************************************/

/*Linker definitions which are specific to Gnuc */
/* IFX_CFG_USE_COMPILER_DEFAULT_LINKER shall be defined in Ifx_Cfg.h
 * to use the default compiler linker varaibles and startup */
#ifndef IFX_CFG_USE_COMPILER_DEFAULT_LINKER

/*Start: Core 0 definitions ********************************************** */

/*C extern defintions */
#define IFX_SSW_CORE_LINKER_SYMBOLS(cpu)                                      \
    extern unsigned int __USTACK##cpu[];      /**< user stack end */          \
    extern unsigned int __ISTACK##cpu[];      /**< interrupt stack end */     \
    extern unsigned int __INTTAB_CPU##cpu[];  /**< interrupt vector table */  \
    extern unsigned int __TRAPTAB_CPU##cpu[]; /**< trap vector table */       \
    extern unsigned int __CSA##cpu[];         /**< context save area begin */ \
    extern unsigned int __CSA##cpu##_END[];   /**< context save area end   */

#define __USTACK(cpu)      __USTACK##cpu
#define __ISTACK(cpu)      __ISTACK##cpu
#define __INTTAB_CPU(cpu)  __INTTAB_CPU##cpu
#define __TRAPTAB_CPU(cpu) __TRAPTAB_CPU##cpu
#define __CSA(cpu)         __CSA##cpu
#define __CSA_END(cpu)     __CSA##cpu##_END
#define __START(cpu)       __START##cpu

#define IFX_SSW_COMMON_LINKER_SYMBOLS() \
    __asm("\t .weak __A8_MEM, __A9_MEM");  /**< ASM extern definitions */     \
    extern unsigned int __START0[];     /**< Pointer to the startup code */   \
    extern unsigned int __START1[];     /**< Pointer to the startup code */   \
    extern unsigned int __START2[];     /**< Pointer to the startup code */   \
    extern unsigned int __START3[];     /**< Pointer to the startup code */   \
    extern unsigned int __START4[];     /**< Pointer to the startup code */   \
    extern unsigned int __START5[];     /**< Pointer to the startup code */

/*Wrapper macros for the tool specific definitions */
#if defined(IFX_USE_SW_MANAGED_INT)
#define __INTTAB(cpu)      ((unsigned int)__INTTAB_CPU##cpu | (unsigned int)0x1FE0)
#else
#define __INTTAB(cpu)      __INTTAB_CPU##cpu
#endif /*defined(IFX_USE_SW_MANAGED_INT) */

#define __TRAPTAB(cpu)     __TRAPTAB_CPU##cpu

#define __SDATA1(cpu)      _SMALL_DATA_
#define __SDATA2(cpu)      _LITERAL_DATA_
#define __SDATA3(cpu)      __A8_MEM
#define __SDATA4(cpu)      __A9_MEM

#endif /*#ifndef IFX_CFG_USE_COMPILER_DEFAULT_LINKER*/

#define IFX_SSW_INLINE   __inline__

#define IFX_SSW_NULL_PTR ((void *)0x0U)

/******************************************************************************/
/*--------------------------------   Typedefs  -------------------------------*/
/******************************************************************************/
typedef volatile union
{
    unsigned int       *ucPtr;
    unsigned int       *usPtr;
    unsigned int       *uiPtr;
    unsigned long long *ullPtr;
} Ifx_Ssw_CTablePtr;

/******************************************************************************/
/*----------------------------   GNU Intrinsics  -----------------------------*/
/******************************************************************************/

extern void Ifx_Ssw_MTCR(const unsigned int, unsigned int) __attribute__ ((intrinsic_function(0x102, 0, "mtcr")));

extern int Ifx_Ssw_MFCR(const unsigned int) __attribute__ ((intrinsic_function(0x101, 0, "mfcr")));

extern void Ifx_Ssw_NOP(void) __attribute__ ((intrinsic_function(0x103, 0, "nop")));

extern void Ifx_Ssw_DSYNC(void) __attribute__ ((intrinsic_function(0x103, 0, "dsync")));

extern void Ifx_Ssw_ISYNC(void) __attribute__ ((intrinsic_function(0x103, 0, "isync")));

extern unsigned int Ifx_Ssw_MINU(unsigned int, unsigned int) __attribute__ ((intrinsic_pseudo(3, "min.u")));

extern int Ifx_Ssw_CLZ(int) __attribute__ ((intrinsic_pseudo(1, "clz")));

#define Ifx_Ssw___setAddressReg(aReg, val)    \
    {__asm("#$$bp");                          \
     __asm("  movh.a\t %a15,"#val "@ha\n");   \
     __asm("  lea\t %a15,[%a15]"#val "@l\n"); \
     __asm("  mov.aa %"#aReg ", %a15\n");     \
     __asm("#$$noadjust");                    \
     __asm("#$$ep"); }

#define Ifx_Ssw_setAddressReg(regNum, val) Ifx_Ssw___setAddressReg(regNum, val)

asm volatile void Ifx_Ssw_moveToDataParam0(unsigned int var)
{
% reg var
! "%d2"
	mov %d2, var
}

asm volatile unsigned int Ifx_Ssw_getDataParam0(void)
{
! "%d2"
	mov %d2, %d2
}

asm volatile void Ifx_Ssw_jumpToFunction(void *fun)
{
% reg fun
	ji fun
}

asm volatile void Ifx_Ssw_jumpToFunctionWithLink(void *fun)
{
% reg fun
	jli fun
}

asm void Ifx_Ssw_jumpBackToLink(void)
{
! "%a11"
	ji %a11
}

IFX_SSW_INLINE void Ifx_Ssw_C_InitInline(void)
{
    extern void __init_main(void);
    __init_main();              /* initialize data */
}

#endif /* IFX_SSW_COMPILERSDCC_H_ */
